package org.alino.core.utils;

import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @Desc 密码工具类
 * @Author by Brant
 * @Date 2017/1/15
 */
public class PwdUtils {
    protected static String hashAlgorithmName = "md5";
    protected static Integer hashIterations = 2;
    protected static boolean storedCredentialsHexEncoded = true;
    /**
     * 获取一个密码加盐字符串
     * */
    public static String getSalt(){
        String salt = new SecureRandomNumberGenerator().nextBytes().toHex();
        return salt;
    }

    private static SimpleHash pwdToSimple(String account, String pwd, String salt){
        return new SimpleHash(hashAlgorithmName,pwd, ByteSource.Util.bytes(account+salt),hashIterations);
    }

    /**
     * MD5密码二次加密
     * */
    public static String pwdToHex(String account,String pwd,String salt){
        return pwdToSimple(account,pwd,salt).toHex();
    }
    /**
     * MD5密码二次加密
     * */
    public static String pwdToBase64(String account,String pwd,String salt){
        return pwdToSimple(account,pwd,salt).toBase64();
    }


    //MD5
    /**
     * Returns a MessageDigest for the given <code>algorithm</code>.
     *
     * @return An MD5 digest instance.
     * @throws RuntimeException
     * when a {@link NoSuchAlgorithmException} is caught
     */
    static MessageDigest getDigest() {
        try {
            return MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Calculates the MD5 digest and returns the value as a 16 element
     * <code>byte[]</code>.
     *
     * @param data Data to digest
     * @return MD5 digest
     */
    public static byte[] md5(byte[] data) {
        return getDigest().digest(data);
    }

    /**
     * Calculates the MD5 digest and returns the value as a 16 element
     * <code>byte[]</code>.
     *
     * @param data
     *            Data to digest
     * @param charset
     *            charset
     * @return MD5 digest
     */
    public static byte[] md5(String data, String charset) {
        try {
            return md5(data.getBytes(charset));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Calculates the MD5 digest and returns the value as a 32 character hex
     * string.
     *
     * @param data
     *            Data to digest
     * @return MD5 digest as a hex string
     */
    public static String md5Hex(byte[] data) {
        return toHexString(md5(data));
    }

    /**
     * Calculates the MD5 digest and returns the value as a 32 character hex
     * string.
     *
     * @param data
     *            Data to digest
     * @param charset
     *            charset
     * @return MD5 digest as a hex string
     */
    public static String md5Hex(String data, String charset) {
        return toHexString(md5(data, charset));
    }

    //HEX
    private static final String HEX_CHARS = "0123456789abcdef";

    /**
     * Converts a byte array to hex string.
     *
     * @param b - the input byte array
     * @return hex string representation of b.
     */
    public static String toHexString(byte[] b) {
        StringBuffer sb = new StringBuffer();
        for (byte aB : b) {
            sb.append(HEX_CHARS.charAt(aB >>> 4 & 0x0F));
            sb.append(HEX_CHARS.charAt(aB & 0x0F));
        }
        return sb.toString();
    }

    /**
     * Converts a hex string into a byte array.
     *
     * @param s - string to be converted
     * @return byte array converted from s
     */
    public static byte[] toByteArray(String s) {
        byte[] buf = new byte[s.length() / 2];
        int j = 0;
        for (int i = 0; i < buf.length; i++) {
            buf[i] = (byte) ((Character.digit(s.charAt(j++), 16) << 4) | Character.digit(s.charAt(j++), 16));
        }
        return buf;
    }
}
